package com.example.finalassignment.service.impl;

import com.example.finalassignment.common.ThreadContext;
import com.example.finalassignment.exception.ServiceException;
import com.example.finalassignment.mapper.TechnologyInfoMapper;
import com.example.finalassignment.mapper.TechnologyMapper;
import com.example.finalassignment.pojo.Technology;
import com.example.finalassignment.pojo.TechnologyInfo;
import com.example.finalassignment.pojo.dto.TechnologyDto;
import com.example.finalassignment.pojo.response.ResultDataResponse;
import com.example.finalassignment.pojo.response.ResultResponse;
import com.example.finalassignment.service.TechnologyService;
import com.example.finalassignment.util.GenerateUtil;
import com.example.finalassignment.util.JwtUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

@Service
@Transactional
public class TechnologyServiceImpl implements TechnologyService {

    private final TechnologyMapper technologyMapper;

    private final TechnologyInfoMapper technologyInfoMapper;

    public TechnologyServiceImpl(TechnologyMapper technologyMapper, TechnologyInfoMapper technologyInfoMapper) {
        this.technologyMapper = technologyMapper;
        this.technologyInfoMapper = technologyInfoMapper;
    }

    /**
     * 编辑一个文章
     */
    @Override
    public ResultResponse editor(TechnologyDto technologyDto) {
        try {
            // 如果没有uuid的话就是添加
            if (technologyDto.getUuid() == null || technologyDto.getUuid().isEmpty()) {
                String uuid = GenerateUtil.generateUUID();
                String userId = JwtUtil.getIdByToken(ThreadContext.getToken());

                Technology technology = new Technology();
                technology.setUuid(uuid);
                technology.setTitle(technologyDto.getTitle());
                technology.setCreateTime(new Date());
                technology.setUserId(userId);
                technology.setContent(technologyDto.getContent());
                technology.setStatus(technologyDto.getStatus() ? 1 : 0);
                technology.setUpdateTime(new Date());
                technology.setHtml(technologyDto.getHtml());

                technologyMapper.insertSelective(technology);

                TechnologyInfo technologyInfo = new TechnologyInfo();
                technologyInfo.setUuid(uuid);
                technologyInfo.setId(0);
                technologyInfo.setDescription(technologyDto.getDescription());
                technologyInfo.setShowPhoto(technologyDto.getShowPhoto());
                technologyInfoMapper.insertSelective(technologyInfo);

                technologyDto.setUuid(uuid);

                if (technologyDto.getStatus()) {
                    return new ResultDataResponse<TechnologyDto>(technologyDto, "发表成功");
                }

                return new ResultDataResponse<TechnologyDto>(technologyDto, "保存成功");
            } else {
                Technology technology = new Technology();
                technology.setUuid(technologyDto.getUuid());
                technology.setTitle(technologyDto.getTitle());
                technology.setUpdateTime(new Date());
                technology.setStatus(technologyDto.getStatus() ? 1 : 0);
                technology.setContent(technologyDto.getContent());
                technology.setHtml(technologyDto.getHtml());

                technologyMapper.updateByPrimaryKeySelective(technology);

                TechnologyInfo technologyInfo = new TechnologyInfo();
                technologyInfo.setUuid(technologyDto.getUuid());
                technologyInfo.setDescription(technologyDto.getDescription());
                technologyInfo.setShowPhoto(technologyDto.getShowPhoto());

                technologyInfoMapper.updateByPrimaryKeySelective(technologyInfo);

                if (technologyDto.getStatus()) {
                    return ResultResponse.success("发表成功");
                }
                return ResultResponse.success("修改成功");
            }
        } catch (Exception e) {
            throw new ServiceException(201);
        }
    }

    @Override
    public ResultDataResponse<List<Map<String, Object>>> getDataByLimit(Integer start, Integer pages) {

//        System.out.printf("%d %d\n",start,pages);

        if(start == null){
            start = 1;
        }

        if(pages == null){
            pages = 2;
        }

        try {
            String userId = JwtUtil.getIdByToken(ThreadContext.getToken());
            List<Map<String, Object>> dataByLimit = technologyMapper.getDataByLimit(userId, (start - 1) * pages, pages);
            List<Map<String, Object>> size = technologyMapper.getAllData(userId);
            Map<String,Object> map = new HashMap<>();
            map.put("total",size.size());
            dataByLimit.add(map);
            return new ResultDataResponse<List<Map<String, Object>>>(dataByLimit);
        }catch (Exception e){
            throw new ServiceException(201);
        }
    }

    @Override
    public ResultDataResponse<List<Map<String, Object>>> getAllDataByLimit(Integer start, Integer pages) {
        if(start == null || start <= 0){
            start = 1;
        }

        if(pages == null){
            pages = 5;
        }


        Integer finalStart = start;
        Integer finalPages = pages;
        CompletableFuture<List<Map<String, Object>>> getAllDataYesLimitCompletableFuture = CompletableFuture.supplyAsync(new Supplier<List<Map<String, Object>>>() {
            @Override
            public List<Map<String, Object>> get() {
                return technologyMapper.getAllDataByLimit((finalStart - 1) * finalPages, finalPages);
            }
        });

        List<Map<String, Object>> getAllDataYesLimit = getAllDataYesLimitCompletableFuture.join();

        List<Map<String, Object>> allDataByNoLimit = technologyMapper.getAllDataByNoLimit();

        Map<String,Object> map = new HashMap<>();
        map.put("total",allDataByNoLimit.size());
        getAllDataYesLimit.add(map);
        return new ResultDataResponse<>(getAllDataYesLimit);
    }
}
